<?php

namespace Biz\service\advertisement;


use Biz\cache\advertisement\CNewUserProfile;
use Biz\cache\advertisement\CUserLabels;
use Biz\cache\advertisement\CUserProfile;
use Biz\model\advertisement\MHhzPositionUserprofile;
use Biz\model\advertisement\MTaskRecord;
use Biz\model\bigData\MUserProfileTags;
use Doraemon\service\position\BasePositionUserprofile;
use Doraemon\service\position\DisplayConstInterface;
use Doraemon\service\position\PositionRoute;
use Doraemon\service\position\Search\UserFilterSchedule;
use Doraemon\service\position\UserProfileModule\SystemType;
use Doraemon\service\UserPortrait\UserPortraitApi;
use Doraemon\tools\HhzClient;
use Doraemon\tools\HhzEnv;
use Doraemon\tools\Log;
use Exception;

/**
 * @property mixed|null $uid 用户uid 实时 5204625
 * @property mixed|null $birthday 生日 实时 19831112
 * @property mixed|null $addtime 注册时间 实时 1539084175
 * @property mixed|null $app_version app版本 4.11.1
 */
class AdUserProfileManagement implements \ArrayAccess
{

    private $_container = [];
    const LOG_NAME = 'UserProfile';
    const CONF_PATH = '/data/wwwroot/g_biz/service/advertisement/static/profile.php';
    const ALIAS_PATH = '/data/wwwroot/g_biz/service/advertisement/static/alias.php';
    const RULES_MODULE_DIR = '/data/wwwroot/g_doraemon/service/position/UserProfileModule/';
    protected static $config = [];
    protected static $alias = [];
    protected static $fields = [];
    protected static $groups = [];
    protected static $labels = [];

    public function __construct($data = []) {
        $this->_container = $data;
    }

    public function __get($value)
    {
        return $this->_container[$value] ?? null;
    }

    public function offsetSet($offset, $value) {
        if (is_null($offset)) {
            $this->_container[] = $value;
        } else {
            $this->_container[$offset] = $value;
        }
    }

    public function offsetExists($offset): bool
    {
        return isset($this->_container[$offset]);
    }

    public function offsetUnset($offset) {
        unset($this->_container[$offset]);
    }

    public function offsetGet($offset) {
        return $this->_container[$offset] ?? null;
    }

    public function toArray()
    {
        return $this->_container;
    }
    public static function log($title, $data)
    {
        Log::position_info(self::LOG_NAME . ' ' . $title, $data);
    }

    public static function getFlByActiveRules($activeRules): array
    {
        $fl = [];
        if (!empty($activeRules)) {
            //获取具体规则id
            $idMap = [];
            foreach ($activeRules as $id => $rules) {
                if (empty($rules)) continue;
                foreach ($rules as $ruleId => $ruleVal) {
                    $idMap[$ruleId] = $ruleId;
                }
            }
            //通过规则id查询配置信息,再通过字段查询用户画像
            if ($idMap) {
                $conf = BasePositionUserprofile::getPositionUserProfileConfig($idMap);
                $fl = array_column($conf, 'column_field');
            }
        }
        return $fl;
    }

    public static function getGroups(): array
    {
        self::getConf();
        return self::$groups;
    }

    public static function getLabels(): array
    {
        self::getConf();
        return self::$labels;
    }

    public static function getFields(): array
    {
        self::getConf();
        return self::$fields;
    }

    public static function getFieldsMap(): array
    {
        self::getConf();
        return array_column(self::$fields, 'column_name', 'column_field');
    }

    public static function getConf()
    {
        if (empty(self::$config)) {
            $config = require_once self::CONF_PATH;
            foreach ($config as $v) {
                if ($v['sign'] == MHhzPositionUserprofile::SIGN_TYPE_LABEL) {
                    self::$labels[] = $v;
                } elseif ($v['sign'] == MHhzPositionUserprofile::SIGN_TYPE_GROUP) {
                    self::$groups[] = $v;
                } else {
                    self::$fields[] = $v;
                }
            }
            self::$config = $config;
        }
        return self::$config;
    }

    public static function writeable($path)
    {
        if (file_exists($path) && !is_writeable($path)) throw new Exception($path . ' 文件不可写,确认权限');
    }

    /**
     * @throws Exception
     */
    public static function setConf($data)
    {
        self::writeable(self::CONF_PATH);
        $conf = var_export($data, true);
        $content = <<<CONTENT
<?php

return $conf

;
CONTENT;
        return file_put_contents(self::CONF_PATH, $content, LOCK_EX);
    }

    public static function getAlias()
    {
        if (empty(self::$alias)) {
            self::$alias = require_once self::ALIAS_PATH;
        }
        return self::$alias;
    }

    public static function makeAlias()
    {
        $list = MUserProfileTags::select(["short_name", "tag", "tagName"], ['tag_type'=> 1, 'is_delete'=> 0]);

        $alias = empty($list) ? [] : array_column($list, null, 'tag');

        if (empty($alias)) exit('数据为空');

        $conf = var_export($alias, true);

        echo <<<CONTENT
<?php

return $conf

;
CONTENT;
    }

    public static function splitConf($conf) {
        $newFields = [];
        $newLabels = [];
        $newGroups = [];
        $entity = new MHhzPositionUserprofile();
        foreach ($conf as $id => $v) {
            if ($v['sign'] == $entity::SIGN_TYPE_GROUP) {
                $newGroups[$id] = $v;
            } elseif ($v['sign'] == $entity::SIGN_TYPE_LABEL) {
                $newLabels[$id] = $v;
            }else {
                $newFields[$id] = $v;
            }
        }
        return [$newFields, $newLabels, $newGroups];
    }

    public static function moduleFileExists($column_field): bool
    {
        $class = PositionRoute::camelize($column_field);
        $path = self::RULES_MODULE_DIR . $class . ".php";
        return file_exists($path);
    }

    public static function writeModuleFile($column_field, $column_name)
    {
        $dir_path = self::RULES_MODULE_DIR;

        if (file_exists($dir_path) && !is_writeable($dir_path)) throw new \Exception($dir_path . ' 文件不可写,确认权限');

        $name = $column_name . " " . $column_field;
        $class = PositionRoute::camelize($column_field);
        $path = $dir_path . $class . ".php";
        $exists = file_exists($path);

        if ($exists) return;

        $template = <<<PHP
<?php

namespace Doraemon\service\position\UserProfileModule;

/**
* $name
* Class $class
* @package Doraemon\service\position\UserProfileModule
*/
class $class extends AbstractUserProfile
{

}
PHP;
        file_put_contents($path, $template);
    }

    /**
     * @throws Exception
     */
    public static function createField($field, $form_type = '', $group_field = '', $write = false)
    {
        $alias = AdUserProfileManagement::getAlias();
        if (!isset($alias[$field])) throw new \Exception('没有标签:' . $field);
        $conf = AdUserProfileManagement::getConf();
        $fields = array_column($conf, null, 'column_field');
        if (isset($fields[$field])) throw new \Exception('已经存在:' . $field);
        $online = $alias[$field];
        list($newFields, $newLabels, $newGroups) = AdUserProfileManagement::splitConf($conf);
        $id = max(array_keys($newFields + $newLabels)) + 1;
        $data = [
            'column_field' => $online['tag'],
            'column_alias' => $online['short_name'],
            'column_name' => $online['tagName'],
            'switch_name' => '',
            'group_field' => $group_field,
            'show_option' => (string)MHhzPositionUserprofile::SHOW_OPTION_AUTO,
            'form_type' => $form_type,
            'form_help' => '',
            'sign' => (string)MHhzPositionUserprofile::SIGN_TYPE_FIELD,
            'id' => $id,
        ];
        $newFields[$id] = $data;
        AdUserProfileManagement::setConf($newFields + $newLabels + $newGroups);

        if ($write) self::writeModuleFile($online['tag'], $online['tagName']);
    }

    public static function sort($sortInfo)
    {
        $conf = AdUserProfileManagement::getConf();

        $new = [];
        foreach ($sortInfo as $id => $sort) {
            $new[$id] = $conf[$id];
            unset($conf[$id]);
        }
        list($newFields, $newLabels, $newGroups) = AdUserProfileManagement::splitConf($conf);
        if (empty($newFields)) $newFields = $new;
        if (empty($newLabels)) $newLabels = $new;
        if (empty($newGroups)) $newGroups = $new;
        AdUserProfileManagement::setConf($newFields + $newLabels + $newGroups);
    }

    public static function getUserProfile($uid, $userProfileExt = [], $fl = [], $token = UserPortraitApi::POSITION_TOKEN): AdUserProfileManagement
    {
        $cache = [];
        if ($uid && $fl && !in_array('management', $fl)) {
            $fl = array_unique(array_merge($fl, ['area_code', 'uid']));
            $cache = UserPortraitApi::request($uid, $fl, $token);
        }

        //实时数据
        $default = ['uid' => $uid];

        if (HhzClient::getClientVersion()) {
            $default['app_version'] = HhzClient::getClientVersion();
            if (isset($cache['app_version']))  $default['old_app_version'] = $cache['app_version'];
        }
        if (HhzClient::getClientType()) $default['system_type'] = SystemType::APP_TYPE_MAP[HhzClient::getClientType()] ?? '';

        return new self($userProfileExt + $default + $cache);
    }


    /**
     * 设置用户画像标签
    */
    public static function setField($uid, $key, $value, $async = false)
    {

        $rs = CNewUserProfile::setOne($uid, $key, $value);
        $es = null;

        if ($async) {
            $hashKey = CNewUserProfile::map($key);

            $es = \Doraemon\service\es\EsUserPortraitNew::updateLabels($uid, [], [$hashKey => $value]);
        }

        self::log(__FUNCTION__, compact('uid', 'key', 'value', 'rs', 'async', 'es'));

        return $rs;
    }

    /**
     * 设置用户af信息
     * @param $uid
     * @param $ad_channel_type     string 投放大类
     * @param $ad_channel_channel  string 投放渠道
     * @param $ad_channel_pos      string 投放位置
     * @param $ad_channel_obj_type string 渠道用户素材类型
     * @param $ad_channel_ad       string 渠道用户落脚点
     * @param $ad_channel_space    string 渠道用户空间
     * @param $ad_channel_ele      string 渠道用户元素
     * @param $ad_channel_topic    string 渠道用户主题
     */
    public static function setAf($uid,
                                 string $ad_channel_type = '',
                                 string $ad_channel_channel = '',
                                 string $ad_channel_pos = '',
                                 string $ad_channel_obj_type = '',
                                 string $ad_channel_ad = '',
                                 string $ad_channel_space = '',
                                 string $ad_channel_ele = '',
                                 string $ad_channel_topic = '')
    {
        $store = [];
        if ($ad_channel_type) $store['ad_channel_type'] = $ad_channel_type;
        if ($ad_channel_channel) $store['ad_channel_channel'] = $ad_channel_channel;
        if ($ad_channel_pos) $store['ad_channel_pos'] = $ad_channel_pos;
        if ($ad_channel_obj_type) $store['ad_channel_obj_type'] = $ad_channel_obj_type;
        if ($ad_channel_ad) $store['ad_channel_ad'] = $ad_channel_ad;
        if ($ad_channel_space) $store['ad_channel_space'] = $ad_channel_space;
        if ($ad_channel_ele) $store['ad_channel_ele'] = $ad_channel_ele;
        if ($ad_channel_topic) $store['ad_channel_topic'] = $ad_channel_topic;
        if ($store) {
            CNewUserProfile::setMulti([$uid => $store]);
            self::log(__FUNCTION__, compact('uid', 'store'));
        }
    }

    /**
     * 设置用户的kol
     */
    public static function setKOL($uid, $kol)
    {
        if ($kol) self::setField($uid, 'ad_channel_kol', $kol);
    }

    /**
     * 设置用户画像自定义标签
     */
    public static function setLabel($uid, $label)
    {
        return CUserLabels::setOne($uid, $label);
    }

}